//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>
#define  MISC
#include "misc.h"

EXTERN_C void __cdecl InterruptThread(void* pArg);

//for mutex
EXTERN_C void __cdecl Mtx_lock(struct mtx *pMtx)
{
    WaitResult wr;
    ((class DzMutex*)(pMtx->pM))->Lock(&wr);
}

EXTERN_C void __cdecl Mtx_unlock(struct mtx *pMtx)
{
    ((class DzMutex*)(pMtx->pM))->Unlock();
}

EXTERN_C void __cdecl Mtx_init(struct mtx *pMtx)
{
    pMtx->pM = (void *)new DzMutex;
}

EXTERN_C void __cdecl Mtx_destroy(mtx* pMtx)
{
    delete(class DzMutex*)(pMtx->pM);
}

class DzMutex g_mutex;

EXTERN_C int NetLock()
{
    WaitResult wr;
    g_mutex.Lock(&wr);
    return 1;
}

EXTERN_C void NetUnlock()
{
    g_mutex.Unlock();
}




//for time
EXTERN_C void __cdecl getmicrotime(struct timeval* time)
{
    SystemTime systemTime;
    DzGetSystemTime(&systemTime);

    time->tv_sec = systemTime.seconds;
    time->tv_usec = systemTime.microseconds;
}


//for event
EXTERN_C void __cdecl Wait(struct Signal *pEvent, int *i)
{
    WaitResult wr;
    ((class DzEvent *)(pEvent->event))->Wait(&wr, (EventState *)i);
}

EXTERN_C void __cdecl PulseByISR(struct Signal *pEvent, int i)
{
    ((class DzEvent *)(pEvent->event))->NotifyByIsr(i);
}

EXTERN_C void __cdecl Pulse(struct Signal *pEvent, int i)
{
    ((class DzEvent *)(pEvent->event))->Notify();
}

EXTERN_C void __cdecl Signal_init(struct Signal *pEvent)
{
    pEvent->event =(void*) new DzEvent;
}

//for physic memery
EXTERN_C int __cdecl PhysAddr(char *va){
    return PHYSADDR(va);
}

//for malloc
EXTERN_C void * __cdecl Malloc(size_t n)
{
//    kprintf("\n, ,size = %d\n", n);
    PTR p = (PTR)malloc(n);
    if (p == NULL) {
        kprintf("\n, ,size = %d\n", n);
        DebugBreak();
    }
    return p;
}



EXTERN_C PTR __cdecl FSMALLOC(UInt32 NBytes, UInt32 Tag, UInt32 Options)
{
//    kprintf("\n, ,size = %d\n", NBytes);
    PTR p = (PTR)malloc(NBytes);
    if(p == NULL) {
        kprintf("\n, ,size = %d\n", NBytes);
        DebugBreak();
    }
    return p;
}

EXTERN_C PTR __cdecl DevMalloc(UInt32 NBytes, UInt32 Tag, UInt32 Options)
{
//    kprintf("\n, ,size = %d\n", NBytes);
    PTR p = (PTR)malloc(NBytes);
    if(p == NULL) {
        kprintf("\n, ,size = %d\n", NBytes);
        DebugBreak();
    }
    return p;
}



EXTERN_C PTR __cdecl KernelAlloc(uint_t uOrder)
{
    PTR p = (PTR)DzAllocKernelPages(uOrder);
    if (p == NULL) {
        kprintf("\n, ,AllocKernelPages size = %d\n", uOrder);
        DebugBreak();
    }
    return p;
}



EXTERN_C PTR __cdecl m_DevMalloc(UInt32 NBytes, UInt32 Tag, UInt32 Options)
{
    PTR p = (PTR)KernelAlloc(mRoundUp2Order((NBytes + 4*1024 - 1)/(4*1024)));
    if(p == NULL) {
        kprintf("\n, ,size = %d\n", NBytes);
        DebugBreak();
    }
    DebugBreak();
    return p;
}

//for free
EXTERN_C void __cdecl FSFREE( PTR Ptr, UInt32 Tag)
{
    free(Ptr);
}


EXTERN_C void __cdecl bzero(void *buf, size_t size)
{
    memset(buf, 0, size);
}

EXTERN_C void __cdecl AddDevice(irq_t irq, ipl_t ipl, isr_t isr, void *pvDevice)
{
    DzRegisterIsr(irq, ipl, isr, pvDevice);
}

//for cv strut
EXTERN_C void __cdecl Cv_init(struct cv *pCv)
{
    pCv->pCon = (void *)new DzCondition;
}
typedef Int64 TIME;
EXTERN_C int __cdecl Cv_timedwait(struct cv *pCv, struct mtx* pMtx, TIME tout)
{
    ((class DzCondition *)(pCv->pCon))->TryWait((class DzMutex*)pMtx->pM, tout, NULL);
    return 0;
}
EXTERN_C void __cdecl Cv_signal(struct cv *pCv)
{
    ((class DzCondition *)(pCv->pCon))->Pulse();
}
EXTERN_C void __cdecl Cv_destroy(struct cv *pCv)
{
    delete(class DzCondition *)(pCv->pCon);
}

//EXTERN_C Boolean  RTL8139Interrupt(void* );

Int32 ThdEntry(void* pArg)
{
    IThread *pCurrentThread = NULL;
    ECode ec = DzGetCurrentThread(&pCurrentThread);
    if (FAILED(ec)) return ec;

    pCurrentThread->SetPriority(ThreadPriority_Highest);
    pCurrentThread->Release();

    InterruptThread(pArg);
    return 0;
}

EXTERN_C void __cdecl CreateThread(void *pArg)
{
    ECode ec;
    UInt32 dwFlags = 0;

    ec = DzCreateKernelThread(ThdEntry, pArg, dwFlags, ThreadPriorityRank_Normal, NULL);
    if (FAILED(ec)) {
        kprintf("*ERROR* failed to create kernelthread\n");
    }
}

EXTERN_C unsigned int __cdecl mRoundUp2Order(unsigned int u)
{
    assert(0 < u);
//    kprintf("\nrd2o %u\n", u);

    if (u == 1) {
        return 0;
    }
    if(u > 1 && u <= 2) {
        return 1;
    }
    if(u > 2 && u <= 4) {
        return 2;
    }
    if(u > 4 && u <= 8) {
        return 3;
    }
    if(u > 8 && u <= 16) {
        return 4;
    }
    if(u > 16 && u <= 32) {
        return 5;
    }
    if(u > 32 && u <= 64) {
        return 6;
    }
    if(u > 64 && u <= 128) {
        return 7;
    }
    if(u > 128 && u <= 256) {
        return 8;
    }
    if(u > 256 && u <= 512) {
        return 9;
    }
    if(u > 512 && u <= 1024) {
        return 10;
    }
    if(u > 1024 && u <= 2048) {
        return 11;
    }
    if(u > 2048 && u <= 4096) {
        return 12;
    }
    if(u > 4096 && u <= 8192) {
        return 13;
    }
    if(u > 8192 && u <= 16384) {
        return 14;
    }
    if(u > 16384 && u <= 32768) {
        return 15;
    }
    if(u > 32768 && u <= 65536) {
        return 16;
    }
    if(u > 65536 && u <= 131072) {
        return 17;
    }
    if(u > 131072 && u <= 262144) {
        return 18;
    }
    if(u > 262144 && u <= 524288) {
        return 19;
    }
    if(u > 524288 && u <= 1048576) {
        return 20;
    }
    if(u > 1048576 && u <= 2097152) {
        return 21;
    }
    if(u > 2097152 && u <= 4194304) {
        return 22;
    }
    if(u > 4194304 && u <= 8388608) {
        return 23;
    }
    if(u > 8388608 && u <= 16777216) {
        return 24;
    }
    if(u > 16777216 && u <= 33554432) {
        return 25;
    }
    return 26;
}
